package com.woniuxy.tools;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.woniuxy.annotation.WoniuTool;
import com.woniuxy.annotation.WoniuToolParam;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author: 马宇航
 * @Description: 函数调用，触发AI获取天气
 * @DateTime: 25/10/30/星期四 15:23
 * @Component: 成都蜗牛学苑
 **/
public class GetWeather {
    //方法名:对象
    static Map<String,Object> method2Object = new HashMap<>();
    @WoniuTool(methodName = "getWeather",description = "获取当前地址的天气")
    public void getWeather(@WoniuToolParam(description = "地名，不说就默认成都",required = true) String address){
        System.out.println("拿到"+address+"的天气是：阴天");
    }

    public static void aiResult(String msg) throws JsonProcessingException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //假设AI已经回复了
        msg = """
                {
                  "model": "llama3.2",
                  "created_at": "2024-07-22T20:33:28.123648Z",
                  "message": {
                    "role": "assistant",
                    "content": "",
                    "tool_calls": [
                      {
                        "function": {
                          "name": "getWeather",
                          "arguments": {
                            "address": "成都"
                          }
                        }
                      }
                    ]
                  },
                  "done_reason": "stop",
                  "done": true,
                  "total_duration": 885095291,
                  "load_duration": 3753500,
                  "prompt_eval_count": 122,
                  "prompt_eval_duration": 328493000,
                  "eval_count": 33,
                  "eval_duration": 552222000
                }
                """;
        ObjectMapper objectMapper = new ObjectMapper();
        JsonNode jsonNode = objectMapper.readTree(msg);
        //1.先拿到方法名
        String methodName = jsonNode.get("message").get("tool_calls").get(0).get("function").get("name").asText();
        System.out.println(jsonNode.get("message").get("tool_calls").get(0).get("function").get("name"));
        //2.再拿到参数
        //先把参数转成json字符串
        String arguments = jsonNode.get("message").get("tool_calls").get(0).get("function").get("arguments").get("address").asText();
        System.out.println(jsonNode.get("message").get("tool_calls").get(0).get("function").get("arguments"));
        //3.从map中取出对象
        GetWeather getWeatherObject = (GetWeather) method2Object.get(methodName);
        //错误，因为我们的方法，是从AI的回复的字符串中取出来的文本，怎么可以直接对象.方法名字符串，就能调用方法？
//        getWeatherObject."getWeather"(arguments);
        //4.通过反射获取类对象
        Class<? extends GetWeather> getWeatherClass = getWeatherObject.getClass();
        //通过反射获取方法：类对象.getMethod(方法名,...参数类型)
        Method method = getWeatherClass.getMethod(methodName, String.class);
        //5.执行方法 反射是什么？ 正射：对象.方法(参数)；反射: 方法.invoke(对象,参数)
        method.invoke(getWeatherObject,arguments);
    }


    //不考虑动态代理，我们现在只需要拼接成 请求的json
    public static void main(String[] args) throws NoSuchMethodException, JsonProcessingException, InvocationTargetException, IllegalAccessException {
        //1.实例化对象
        GetWeather getWeather = new GetWeather();
        //2.通过反射拿到类对象
        Class<? extends GetWeather> weatherClass = getWeather.getClass();
        method2Object.put("getWeather",getWeather);
        //3.拿到对应的方法
        Method weatherMethod = weatherClass.getMethod("getWeather", String.class);
        //4.通过注解拿到方法上的自定义注解
        WoniuTool woniuTool = weatherMethod.getAnnotation(WoniuTool.class);
        //5.拿到方法的参数注解
        Parameter[] parameters = weatherMethod.getParameters();
        System.out.println("第一个参数名字:"+parameters[0].getName());//address
        System.out.println("第一个参数type:"+parameters[0].getType());
        WoniuToolParam annotation = parameters[0].getAnnotation(WoniuToolParam.class);
        System.out.println("第一个参数的描述:"+annotation.description());
        System.out.println("第一个参数的描述:"+annotation.required());
        String json= """
                "tools": [
                    {
                      "type": "function",
                      "function": {
                        "name": "%s",
                        "description": "%s",
                        "parameters": {
                          "type": "object",
                          "properties": {
                            "%s": {
                              "type": "%s",
                              "description": "%s"
                            },
                          },
                          "required": ["%s"]
                        }
                      }
                    }
                  ]
                """.formatted(woniuTool.methodName(),woniuTool.description(),
                parameters[0].getName(),parameters[0].getType().getSimpleName()
                ,annotation.description(),parameters[0].getName());
        System.out.println(json);
        aiResult("");
    }
}
